/************************************************************************/
/* Resources                                                            */
/************************************************************************/
#include "Resources/ResourceManager.h"

namespace TD_Resources {

	map<string, weak_ptr<Resource> > ResourceManager::m_objStringMap = map<string, weak_ptr<Resource> > ();
	/************************************************************************/
	/* ctors and dtors                                                      */
	/************************************************************************/

	ResourceManager::ResourceManager() {

	}

	ResourceManager::ResourceManager(const ResourceManager &rhs) {

	}

	ResourceManager & ResourceManager::operator= (const ResourceManager &rhs) {
		return(*this);
	}
	ResourceManager::~ResourceManager() {

	}

	/************************************************************************/
	/* Functionalities                                                      */
	/************************************************************************/
	shared_ptr<Tileset> ResourceManager::loadCharacterTileset(string resourcePath, Coord2D tileSize, const Color &keyColor /* = Color::BLACK */) {
		/** Relocating the resource to the correct path (depends on architecture)*/ 
		string newResourcePath = resourcePath;

		shared_ptr<Resource> pResource = getInstance()->getObject(newResourcePath).lock();
		shared_ptr<Tileset> pTileset;
		
		if(pResource == NULL) {
			pTileset = shared_ptr<Tileset>(new Tileset(newResourcePath));

			try {
				pTileset->loadCharacterTileset(newResourcePath, tileSize, keyColor);
			} catch(ios_base::failure f) {
				cerr << "#### Caught exception: " << f.what() << endl;
			}

			getInstance()->createObject(newResourcePath, pTileset);
			
		} else {
			pTileset = shared_ptr<Tileset>(static_pointer_cast<Tileset>(pResource));
		}
		
		return(pTileset);
	}

	shared_ptr<Tileset> ResourceManager::loadTileset(const string &resourcePath, Coord2D tileSize, const Color &keyColor /* = Color::BLACK */) {
		/** Relocating the resource to the correct path (depends on architecture)*/
		/** Since it is an image, it depends on resourcesImgPath too.*/
		string newResourcePath = TD_Game::resourcesRoot + TD_Game::resourcesImgPath + resourcePath;

		shared_ptr<Resource>pResource = getInstance()->getObject(newResourcePath).lock();
		shared_ptr<Tileset>pTileset;

		if(pResource == NULL) {
			pTileset = shared_ptr<Tileset>(new Tileset(newResourcePath));

			try {
				pTileset->loadTileset(newResourcePath, tileSize, keyColor);
			} catch(ios_base::failure f) {
				cerr << "#### Caught exception: " << f.what() << endl;
			}

			getInstance()->createObject(newResourcePath, pTileset);

		} else {
			pTileset = shared_ptr<Tileset>(static_pointer_cast<Tileset>(pResource));
		}
		return(pTileset);
	}

	shared_ptr<SDLFont> ResourceManager::loadFont(const string &fontPath, unsigned int fontSize) {
		stringstream newFontPath;
		//Apend the font size to the path that identifies the font
		newFontPath << fontPath << fontSize;
		shared_ptr<Resource>pResource = getInstance()->getObject(TD_Game::resourcesRoot + newFontPath.str()).lock();
		shared_ptr<SDLFont>pFont;
		if(pResource == NULL) {
			//Here the font is loaded only with the path, without font size, so why it is only fontpath
			pFont = shared_ptr<SDLFont>(new SDLFont(TD_Game::resourcesRoot + fontPath, fontSize));
			getInstance()->createObject(TD_Game::resourcesRoot + newFontPath.str(), pFont);
		} else {
			pFont = shared_ptr<SDLFont>(static_pointer_cast<SDLFont>(pResource));
		}
		return(pFont);
	}


	shared_ptr<SDLImage> ResourceManager::loadImage(const string &imagePath) {
		/** Relocating the resource to the correct path (depends on architecture)*/
		/** Since it is an image, it depends on resourcesImgPath too.*/
		string newResourcePath = TD_Game::resourcesRoot + TD_Game::resourcesImgPath + imagePath;

		shared_ptr<Resource> pResource = getInstance()->getObject(newResourcePath).lock();
		shared_ptr<SDLImage> pImg;
		if(pResource == NULL) {
			pImg = shared_ptr<SDLImage>(new SDLImage(newResourcePath));
			
			try {
				pImg->loadFile(newResourcePath);
			} catch(ios_base::failure f) {
				cerr << "#### Caught exception: " << f.what() << endl;
			}

			getInstance()->createObject(newResourcePath, pImg);
		} else {
			pImg = shared_ptr<SDLImage>(static_pointer_cast<SDLImage>(pResource));
		}
		return(pImg);
	}

	shared_ptr<SDLImage> ResourceManager::loadImage(const string &imagePath, const Color &keyColor) {
		/** Relocating the resource to the correct path (depends on architecture)*/
		/** Since it is an image, it depends on resourcesImgPath too.*/
		string newResourcePath = TD_Game::resourcesRoot + TD_Game::resourcesImgPath + imagePath;

		shared_ptr<Resource> pResource = getInstance()->getObject(newResourcePath).lock();
		shared_ptr<SDLImage> pImg;
		if(pResource == NULL) {
			pImg = shared_ptr<SDLImage>(new SDLImage(newResourcePath));
			pImg->loadColorKeyFile(newResourcePath, keyColor);
			getInstance()->createObject(newResourcePath, pImg);
		} else {
			pImg = shared_ptr<SDLImage>(dynamic_pointer_cast<SDLImage>(pResource));
		}
		return(pImg);
	}

	shared_ptr<SDLMusic> ResourceManager::loadMusic(const string &musicPath) {
		shared_ptr<Resource> pResource = getInstance()->getObject(TD_Game::resourcesRoot + musicPath).lock();
		shared_ptr<SDLMusic> pMusic;
		if(pResource == NULL) {
			pMusic = shared_ptr<SDLMusic>(new SDLMusic(TD_Game::resourcesRoot + musicPath));
			pMusic->loadFile(TD_Game::resourcesRoot + musicPath);
			getInstance()->createObject(TD_Game::resourcesRoot + musicPath, pMusic);
		} else {
			pMusic = shared_ptr<SDLMusic>(dynamic_pointer_cast<SDLMusic>(pResource));
		}
		return(pMusic);
	}
	shared_ptr<SDLSound> ResourceManager::loadSound(const string &soundPath) {
		shared_ptr<Resource> pResource = getInstance()->getObject(TD_Game::resourcesRoot + soundPath).lock();
		shared_ptr<SDLSound> pSound;
		if(pResource == NULL) {
			pSound = shared_ptr<SDLSound>(new SDLSound(TD_Game::resourcesRoot + soundPath));
			pSound->loadFile(TD_Game::resourcesRoot + soundPath);
			getInstance()->createObject(TD_Game::resourcesRoot + soundPath, pSound);
		} else {
			pSound = shared_ptr<SDLSound>(dynamic_pointer_cast<SDLSound>(pResource));
		}
		return(pSound);
	}

   shared_ptr<XMLDoc> ResourceManager::loadXMLDocument(const string &xmlPath)
   {
      shared_ptr<Resource> pResource = getInstance()->getObject(TD_Game::resourcesRoot + xmlPath).lock();
      shared_ptr<XMLDoc> pXML;
      if(pResource == NULL) {
         pXML = shared_ptr<XMLDoc>(new XMLDoc(TD_Game::resourcesRoot + xmlPath.c_str()));
         pXML->loadFile(); //CUIDAR REWIND
         getInstance()->createObject(TD_Game::resourcesRoot + xmlPath, pXML);
      } else {
         pXML = shared_ptr<XMLDoc>(dynamic_pointer_cast<XMLDoc>(pResource));
      }
      return(pXML);
   }


}